#ifndef _SG_INTERFACE_LUA_H_
#define _SG_INTERFACE_LUA_H_

#include <vector>
#include <string>

#define _LUA_SAFE_MODE_

class LuaInterface {
    public:
        LuaInterface();
        ~LuaInterface();

        typedef enum {} LUA_NIL;
        static LUA_NIL NIL;

        /**
         * Load and execute the script in the following file
         * NOTE: working directory may not be that which it's in
        **/
        bool loadScript(std::string filename) const;

        /**
         * Create an error with the given string
        **/
        void error(std::string str) const;

        /**
         * Put data into lua
        **/
        class istream {
            public:
                istream( struct lua_State *  state     );
                istream( const LuaInterface& interface );

                istream& operator >> (LUA_NIL       value);
                istream& operator >> (bool          value);
                istream& operator >> (void*         value);
                istream& operator >> (float         value);
                istream& operator >> (int           value);
                istream& operator >> (std::string&  value);
                istream& operator >> (LuaInterface& value);

                const size_t size() const;
            private:
                struct lua_State * m_state;
                int                m_argument;
        };

        /**
         * Get information from lua
        **/
        class ostream {
            public:
                ostream( struct lua_State *  state     );
                ostream( const LuaInterface& interface );

                ostream& operator << (LUA_NIL       value);
                ostream& operator << (bool&         value);
                ostream& operator << (void*&        value);
                ostream& operator << (float&        value);
                ostream& operator << (int&          value);
                ostream& operator << (std::string&  value);
                ostream& operator << (LuaInterface& value);
                //define LUA_TTABLE		    5
                //define LUA_TFUNCTION		6
                //define LUA_TUSERDATA		7
                //define LUA_TTHREAD		8

                const size_t size() const;
            private:
                struct lua_State * m_state;
                const int          m_arguments;
                int                m_argument;
        };

        /**
         * Call a lua function
        **/
        typedef void (*Function) (LuaInterface::istream& returns, LuaInterface::ostream& parameters);

        friend LuaInterface::ostream& operator << (LuaInterface::ostream& os, LuaInterface::Function& value);

        void registerFunction(std::string name, LuaInterface::Function func);
    private:
        /**
         * lua machine state
        **/
        struct lua_State * m_state;
        
        /** Load auxiliary helper libraries
         *
        **/
        void loadAuxLibs();

        /**
         *
        **/
        static std::vector<Function> function_registry;
};

#endif
